package refactorplugin.views;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Observable;
import java.util.Observer;
import model.CodeRefactoringModel;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.part.*;
import org.eclipse.jface.viewers.*;
import org.eclipse.jface.action.*;
import org.eclipse.ui.*;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.SWT;
import presenters.Presenter;
import entity.TaskInfo;
import events.EventGenerator;
import events.ViewEvent;
import views.TaskInfoCellModifier;
import views.TaskInfoLabelProvider;
import views.ViewContentProvider;

/**
 * This sample class demonstrates how to plug-in a new
 * workbench view. The view shows data obtained from the
 * model. The sample creates a dummy model on the fly,
 * but a real implementation would connect to the model
 * available either in this or another plug-in (e.g. the workspace).
 * The view is connected to the model using a content provider.
 * <p>
 * The view uses a label provider to define how model
 * objects should be presented in the view. Each
 * view can present the same model objects using
 * different labels and icons, if needed. Alternatively,
 * a single label provider can be shared between views
 * in order to ensure that objects of the same type are
 * presented in the same way everywhere.
 * <p>
 */

public class SampleView2 extends ViewPart implements Observer {

	/**
	 * The ID of the view as specified by the extension.
	 */
	public static final String ID = "refactorplugin.views.SampleView";

	private TableViewer _viewer = null;
	
	private Action _performAction = null;
	
	private Action _undoAction = null;
	
	private Action _setParamsAction = null;
	
	private Object _notificationObject = null;
	
	private CodeRefactoringModel _model = null;
	
	private EventGenerator _eventGenerator = null;

	private Presenter _presenter = null;
	
	/**
	 * The constructor.
	 */
	public SampleView2() {
		_model = new CodeRefactoringModel();
		_model.addObserver(this);
		_model.updateNotify();
		_eventGenerator = new EventGenerator();
		_presenter  = new Presenter(_model);
		_eventGenerator.addObserver(_presenter);
	}
	
	/**
	 * SampleView is a View from the architecture pattern Model-View-Presenter.
	 * Is observes the events happened on the Model.
	 */
	@Override
	public void update(Observable arg0, Object notificationObject) {
		if (_viewer!=null) {
			_viewer.getTable().clearAll();
			_viewer.setInput(notificationObject);
			_viewer.refresh();
		} else {
			System.out.println("_viewer==null");
			_notificationObject = notificationObject;
		}
	}
	
	private void editTaskInfoForm(TaskInfo serializedMap) {
		Display display =_viewer.getControl().getDisplay();
		final Shell shell = new Shell(display);//_viewer.getControl().getShell();
		shell.setText("Set task parameters");
		final TaskInfo taskInfo = serializedMap;
		int x=0,y=0;
		final Map<String, Text> textFields = new HashMap<String, Text>();
		for (String key : serializedMap.getParameters().keySet()) {
			Label currentKey = new Label(shell,SWT.WRAP);
			currentKey.setText(key);
			currentKey.setLocation(x, y);
			currentKey.pack();
			Text currentValue = new Text(shell, SWT.BORDER);//SWT.SINGLE);//.WRAP);//.NONE);
			currentValue.setText(serializedMap.getParameters().get(key));
			currentValue.setLocation(x+70, y);
			currentValue.pack();
			textFields.put(key,currentValue);
			y+=23;
		}
		
		Button save = new Button(shell,SWT.SAVE);
		save.setText("Save parameters");
		save.setLocation(0/*shell.getSize().x/2-save.getSize().x/2*/, y);
		save.addSelectionListener(new SelectionListener() {
			@Override
			public void widgetSelected(SelectionEvent arg0) {
				for (String key : taskInfo.getParameters().keySet())
					taskInfo.getParameters().put(key, textFields.get(key).getText());
				System.out.println("taskInfo "+taskInfo);
				shell.close();
				_viewer.refresh();				
			}
			
			@Override
			public void widgetDefaultSelected(SelectionEvent arg0) {
			}
		});
		save.pack();
		shell.pack();
		shell.open ();
	}
	
	/**
	 * This is a callback that will allow us
	 * to create the viewer and initialize it.
	 */
	public void createPartControl(Composite parent) {
		_viewer = new TableViewer(parent);//, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
		
		final Table table = _viewer.getTable();
		
		TableColumn taskDescriptionColumn = new TableColumn(table, SWT.LEFT);
		taskDescriptionColumn.setText("Task description");
		taskDescriptionColumn.setWidth(500);
		
		TableColumn isActiveColumn = new TableColumn(table, SWT.LEFT);
		isActiveColumn.setText("Is active");
		isActiveColumn.setWidth(55);
		
		TableColumn targetModuleColumn = new TableColumn(table, SWT.LEFT);
		targetModuleColumn.setText("Target module");
		targetModuleColumn.setWidth(150);
		
		TableColumn endedWithErrorComment = new TableColumn(table, SWT.LEFT);
		endedWithErrorComment.setText("Ended with error");
		endedWithErrorComment.setWidth(120);
		
		TableColumn parametersColumn = new TableColumn(table, SWT.LEFT);
		parametersColumn.setText("Parameters");
		parametersColumn.setWidth(120);

		table.setHeaderVisible(true);
		table.setLinesVisible(true);
		
		_viewer.setContentProvider(new ViewContentProvider());
		_viewer.setLabelProvider(new TaskInfoLabelProvider()/*DependenciesLabelProvider()*/);
		_viewer.setSorter(null);
		_viewer.setCellModifier(new TaskInfoCellModifier(_viewer));
		if (_notificationObject!=null)
			_viewer.setInput(_notificationObject);

		// Create the help context id for the viewer's control
		PlatformUI.getWorkbench().getHelpSystem().setHelp(_viewer.getControl(), "RefactorPlugin.viewer");
		makeActions();
		hookContextMenu();
		//hookDoubleClickAction();
		contributeToActionBars();

	}

	private void hookContextMenu() {
		MenuManager menuMgr = new MenuManager("#PopupMenu");
		menuMgr.setRemoveAllWhenShown(true);
		menuMgr.addMenuListener(new IMenuListener() {
			public void menuAboutToShow(IMenuManager manager) {
				SampleView2.this.fillContextMenu(manager);
			}
		});
		Menu menu = menuMgr.createContextMenu(_viewer.getControl());
		_viewer.getControl().setMenu(menu);
		getSite().registerContextMenu(menuMgr, _viewer);
	}

	private void contributeToActionBars() {
		IActionBars bars = getViewSite().getActionBars();
		fillLocalPullDown(bars.getMenuManager());
		fillLocalToolBar(bars.getToolBarManager());
	}

	private void fillLocalPullDown(IMenuManager manager) {
		manager.add(_performAction);
		manager.add(_undoAction);
		manager.add(_setParamsAction);
		//manager.add(new Separator());
		//manager.add(action2);
	}

	private void fillContextMenu(IMenuManager manager) {
		manager.add(_performAction);
		//manager.add(action2);
		// Other plug-ins can contribute there actions here
		//manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
		manager.add(_undoAction);
		manager.add(_setParamsAction);
	}
	
	private void fillLocalToolBar(IToolBarManager manager) {
		manager.add(_performAction);
		manager.add(_undoAction);
		manager.add(_setParamsAction);
		//manager.add(action2);
	}

	private void makePerform() {
		_performAction = new Action() {
			public void run() {
				IStructuredSelection selection = (IStructuredSelection)_viewer.getSelection();
				System.out.println("SELECTION: "+selection);
				_eventGenerator.generate(selection.toList(), "perform");
			}
		};
		_performAction.setText("Perform");
		_performAction.setToolTipText("Perform task work");
		_performAction.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().
			getImageDescriptor(ISharedImages.IMG_TOOL_REDO));
	}
	
	private void makeUndo() {
		_undoAction = new Action() {
			public void run() {
				IStructuredSelection selection = (IStructuredSelection)_viewer.getSelection();
				_eventGenerator.generate(selection.toList(), "undo");
			}
		};
		_undoAction.setText("Undo");
		_undoAction.setToolTipText("Undo task work");
		_undoAction.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().
			getImageDescriptor(ISharedImages.IMG_TOOL_UNDO));
	}
	
	private void makeSetParams() {
		_setParamsAction = new Action() {
			public void run() {
				IStructuredSelection selection = (IStructuredSelection)_viewer.getSelection();
				List<TaskInfo> selections = selection.toList();
				editTaskInfoForm(selections.get(0));
			}
		};
		_setParamsAction.setText("Set parameters");
		_setParamsAction.setToolTipText("Set task parameters");
		_setParamsAction.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().
			getImageDescriptor(ISharedImages.IMG_ETOOL_PRINT_EDIT));//.IMG_TOOL_NEW_WIZARD));//.IMG_TOOL_UNDO));
	}
	
	private void makeActions() {
		makePerform();
		makeUndo();
		makeSetParams();		
	}

	/**
	 * Passing the focus request to the viewer's control.
	 */
	public void setFocus() {
		_viewer.getControl().setFocus();
	}

}